#include <yatak/kheap.h>
#include <yatak/mutex.h>
#include <keyboard.h>
#include <string.h>
#include <screen.h>
#include <types.h>
#include <list.h>
#include <map.h>
#include <log.h>

multi_map_t * logs = NULL;

void init_log ()
{
	add2multi_map(&logs,"System_log\0","Init system log",sizeof ("Init system log"));
}

// In the future need to create streams and mutex will be in the stream
static int lprintf(const char *fmt, ...)
{
	//uint32 flags;
	//save_flags (flags);
	//cli ();
	static mutex_t mutex;
	char buffer[1024];
	va_list args;
	int i;
	
	mutex_enter (&mutex);

	va_start(args, fmt);
	i=vsprintf(buffer,fmt,args);
	va_end(args);

	if(i>=0)
	{
		print(buffer, i);
	}

	//restore_flags (flags);
	mutex_leave (&mutex);
	return i;
}

int write_log (char * log_name, char * msg, size_t size_msg)
{
	if (!logs)
		init_log ();
	if (!log_name || !msg || !size_msg)
		return 1;
	add2multi_map(&logs,log_name,msg,size_msg);
}

int read_log (char * buf [], int max_len, char * log_name, int from, int number)
{
	list_t * log_str;
	log_str = get_multi_map_items (logs,log_name);
	if (!log_str || number <= 0)
		return 1;
	int i, j, stat_a = 0;
	for (i = from-1, j = 0; i <= (number-1); i++, j++)
	{
		if (buf[j] == '\0')
		{
			stat_a = 1;
			break;
		}
	}
	if (stat_a)
	{
		char * b;
		for (i = from-1, b = buf; i <= (number-1); i++, b+=max_len)
		{
			strcpy (b,(char *)get_list_item (log_str,i));
			b [get_list_item_s (log_str,i)] = '\0';
		}
	}
	else
	{
		for (i = from-1, j = 0; i <= (number-1); i++, j++)
		{
			strcpy (buf[j],(char *)get_list_item (log_str,i));
			buf [j] [get_list_item_s (log_str,i)] = '\0';
		}
	}
	return 0;
}

void print_log (char * log_name)
{
//	char screen_arr[24][256];
 	char **screen_arr;
	int h = GetTtyHeight()-1;
	int start = 1, finish = h;
 	screen_arr = (char **)kmalloc(sizeof(char *)*h);
 	int i;
 	for (i = 0; i < h; i++)
 		screen_arr [i] = (char *)kmalloc(sizeof(char)*256);
	int need_read = 1, need_print = 1,pos_arr = 0,need_exit = 0;
	asm volatile ("hlt");
	cls ();
	do
	{
		if (need_read)
		{
			read_log (screen_arr,256,log_name,start,finish);
			start = finish+1;
			finish += h;
			pos_arr = 0;
			need_read = 0;
		}
		if (need_print)
		{
			for (; pos_arr < h; pos_arr++)
			{
				if (!strlen(screen_arr[pos_arr]))
				{
					need_exit = 1;
					while (GetYCoord() != 24)
						kprintf ("\n");
					break;
				}
				lprintf ("%s\n",screen_arr[pos_arr]);
				if (GetYCoord() == 24)
				{
					pos_arr++;
					break;
				}
			}
			if (pos_arr == h)
				need_read = 1;
		}
		lprintf(":");
		char ch = in_char (true);
		if (ch == 'q' || ch == 'Q')
			break;
		if (ch == '\n' && !need_exit)
		{
			need_print = 1;
			lprintf ("\b");
			set_csr(0,GetYCoord());
		}
		else
		{
			need_print = 0;
			lprintf ("\b");
		}
	}
	while (1);
 	for (i = 0; i < h; i++)
 		kfree(screen_arr [i]);
 	kfree(screen_arr);
	cls ();
}